//
//  main.c
//  C 面向指针编程
//
//  Created by Robin on 16/4/4.
//  Copyright © 2016年 cnbm. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <gc.h>

// 模拟一个链条

//链条的一节
struct node {
    
    struct node *pre;
    struct node *next;
    void *shape;
};

struct pair {
    void *first;
    void *second;
};

struct pair *create_pair (void *a,void *b){
    
    struct pair *p = GC_MALLOC_ATOMIC(sizeof(struct pair));
    p->first = a;
    p->second = b;
    return p;
}

struct pair* pair_for_double_type (double x,double y);

double* malloc_double (double value);

/**创建一个矩形的shape*/
void * rectangle_shape ();

/**创建一个其他形状的shape*/
void * elliptic_shape ();

struct node *create_chain_node(void* (*fp)(void));

//void release (struct node *chain_node);

#pragma mark - main function
int main(int argc, const char * argv[]) {
    
    struct node *head = create_chain_node(rectangle_shape);
    
    struct node *tail = head;
    
    for (int i=0; i<1000; i++) {
        
        struct node *new_node = create_chain_node(rectangle_shape);
        tail->next = new_node;
        new_node->pre = tail;
        tail = new_node;
    }

    tail->next = head;
    head->pre = tail;
    
    //release(head);

    return 0;
}


double* malloc_double (double value){

    //GC_INIT();
    double *d = GC_MALLOC_ATOMIC(sizeof(double));
    *d = value;
    return d;
}

struct pair* pair_for_double_type (double x,double y){
    
    struct pair *ret = GC_MALLOC_ATOMIC(sizeof(struct pair));
    ret->first = malloc_double(x);
    ret->second = malloc_double(y);
    return ret;
}

void * rectangle_shape (void){
    struct pair *left_hole = create_pair(pair_for_double_type(1.0, 1.0), malloc_double(0.5));
    struct pair *right_hole = create_pair(pair_for_double_type(9.0, 1.0), malloc_double(0.5));
    struct pair *holes = create_pair(left_hole, right_hole);
    struct pair *body = create_pair(malloc_double(10.0), malloc_double(2.0));
    struct pair *shape = create_pair(body, holes);
    return shape;
}

//void * elliptic_shape (){
//    
//    
//}

//struct node *create_chain_node(void* (*fp)(void)){
//    struct node *node = malloc(sizeof(struct node));
//    node->next = NULL;
//    node->pre = NULL;
//    node->shape = fp();
//    return node;
//}

struct node *create_chain_node(void* (*fp)(void)){
    struct node *node = GC_MALLOC_ATOMIC(sizeof(struct node));
    node->next = NULL;
    node->pre = NULL;
    node->shape = fp();
    return node;
}

//int i = 0;

//#warning 一个半吊子的释放内存方法 待改进 暂时先用 bdw_gc 实现内存自动管理
//void release (struct node *chain_node){
//
//    struct node *next = chain_node;
//    
//    for (int j=0; next->next != chain_node; j++) {
//        
//        //i++;
//        //printf("执行了多少次 %d",i);
//
//        struct node *curr_node = next;
//        
//        if (next->shape) {
//            //free(chain_node->shape);
//            
//            struct pair *shape_struct = next->shape;
//            
//            if (shape_struct->first) {
//                struct pair *body = shape_struct->first;
//                if (body) {
//                    free(body->first);
//                    free(body->second);
//                }
//            }
//            
//            if (shape_struct->second) {
//                struct pair *circles = shape_struct->second;
//                
//                if (circles) {
//                    
//                    if (circles->first) {
//                        
//                        struct pair *point = circles->first;
//                        free(point->first);
//                        free(point->second);
//                        free(circles->first);
//                    }
//                    
//                    if (circles->second) {
//                        struct pair *point = circles->second;
//                        free(point->first);
//                        free(point->second);
//                        free(circles->second);
//                    }
//                    
//                    free(circles);
//                }
//            }
//            
//            free(shape_struct);
//        }
//        
//        //struct node *pre = next->pre;
//
//        next = next->next;
//
//        free(curr_node);
//        
//
//    }
//    
//}




